package com.jdy.nettle.service;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jdy.entity.FileData;
import com.jdy.nettle.mapper.FileMapper;
import com.jdy.utils.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.function.Consumer;


/**
 *
 */
@Service
public class FileWatchService extends ServiceImpl<FileMapper, FileData> {
    private static final Logger log = LoggerFactory.getLogger(FileWatchService.class);

    @Value("${server.watch.file-path}")
    private String rootDir;

    /**
     * 监控服务
     */
    private WatchService service;

    private FileChangeListener listener = new FileChangeListener() {
        @Override
        public void onCreate(String fileName) {
            log.info("[新建]:{}", fileName);
            String[] split = FileUtils.clearSuffix(fileName).split("-");
            FileUtils.readExcel(rootDir + File.separator + fileName, FileData.class, (Consumer<List<FileData>>) list -> {
                for (FileData data : list) {

                    data.setB(split[0] + data.getB());
                    data.setC(split[1] + data.getC());
                    data.setD(split[2] + data.getD());

                    if (!insert(data))
                        log.info("数据插入到数据库失败！ {}", data);
                    log.info("数据插入到数据库失败！ {}", data);
                }
            });
        }

        @Override
        public void onModify(String fileName) {
            log.info("[修改]: {}", fileName);
        }

        @Override
        public void onDelete(String fileName) {
            log.info("[删除]:{}", fileName);
        }
    };


    private boolean insert(FileData data) {
        return baseMapper.insert(data) > 0;
    }

    public void start() {
        if (service == null)
            initService();
        try {
            log.info("开始启动对目录{}下文件创建监听", rootDir);
            startService();
            log.info("文件监听结束！");
        } catch (Exception e) {
            log.info("启动监听器失败！！！[{}]", e.getMessage(), e);
        }
    }

    @SuppressWarnings("unchecked")
    private void startService() throws InterruptedException {
        while (true) {
            WatchKey key = service.take();
            for (WatchEvent<?> watchEvent : key.pollEvents()) {
                final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
                final Path filePath = watchEventPath.context();
                String fileName = filePath.toString();
                if (fileName.startsWith("~$")) continue;
                final WatchEvent.Kind<?> kind = watchEvent.kind();
                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    //丢失或放弃事件时被触发
                    log.debug("{} 文件丢失！", fileName);
                } else if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
                    //当新的文件夹或者文件出现时
                    listener.onCreate(fileName);
                } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
                    //当有任意文件被修改时
                    listener.onModify(fileName);
                } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
                    //当文件夹或者文件消失时
                    listener.onDelete(fileName);
                }
            }
            //WatchKey实例通过poll或者take返回后，就不会捕获任何事件
            //调用reset()方法就可以将这个WatchKey重新回到WatchService队列，可以重新等待新的事件。
            boolean valid = key.reset();
            if (!valid) break;
        }
    }

    private void initService() {
        final Path path = Paths.get(rootDir);
        try {
            service = FileSystems.getDefault().newWatchService();
            path.register(service, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY,
                    StandardWatchEventKinds.ENTRY_DELETE);
        } catch (IOException e) {
            log.info("初始化监听器失败！！！[{}]", e.getMessage(), e);
        }


    }

    public interface FileChangeListener {

        void onCreate(String fileName);

        void onModify(String fileName);

        void onDelete(String fileName);
    }
}
